#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    subProductModel = new QStandardItemModel;
    suppliersModel = new QStandardItemModel;
    solutionModel = new QStandardItemModel;
    ui ->solutionTable->setModel(solutionModel);
    ui ->solutionTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
    solutionModel->setColumnCount(2);
    processBase = new DataBase();
    ui->my_plot->addGraph();
    ui->my_plot->addGraph();
    /*QVector<double> x(101), y(101); // initialize with entries 0..100
    for (int i=0; i<101; ++i)
    {
      x[i] = i/50.0 - 1; // x goes from -1 to 1
      y[i] = x[i]*x[i];  // let's plot a quadratic function
    }
    // create graph and assign data to it:

    ui->my_plot->graph(0)->setData(x, y);
    // give the axes some labels:
    ui->my_plot->xAxis->setLabel("x");
    ui->my_plot->yAxis->setLabel("y");
    // set axes ranges, so we see all data:
    ui->my_plot->xAxis->setRange(-1, 1);
    ui->my_plot->yAxis->setRange(0, 1);*/
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::loadBase(DataBase *newBase){
  //dopisac funkcje setupModel ;)
  Product temp;
  Supplier supTemp;
  int position;
  QModelIndex index;
  subProductModel->clear();
  suppliersModel->clear();
  subProductModel->setColumnCount(3);
  suppliersModel->setColumnCount(5);
//  subProductModel->setRowCount(newBase->countProducts());
  for(int i = 0;i<newBase->countProducts();i++){
        temp = newBase->getProduct(i);
        position = subProductModel->rowCount();
        subProductModel->insertRow(position);
        subProductModel->setData(subProductModel->index(position,0),QVariant().fromValue(temp.getName()));
        subProductModel->setData(subProductModel->index(position,1),QVariant().fromValue(temp.getQuantity()));
        subProductModel->setData(subProductModel->index(position,2),QVariant().fromValue(temp.getUnit()));

        for(int j=0;j<temp.countSuppliers();j++){
            supTemp = temp.getSupplier(j);
            position = suppliersModel->rowCount();
            suppliersModel->insertRow(position);
            suppliersModel->setData( suppliersModel->index(position,0),QVariant().fromValue(supTemp.getName()) );
            suppliersModel->setData( suppliersModel->index(position,1),QVariant().fromValue(temp.getName()) );
            suppliersModel->setData( suppliersModel->index(position,2),QVariant().fromValue(supTemp.getCost()) );
            suppliersModel->setData( suppliersModel->index(position,3),QVariant().fromValue(supTemp.getProductionTime() ) );
            suppliersModel->setData( suppliersModel->index(position,4),QVariant().fromValue(supTemp.getQuantityAvalaiblePerDay()) );
        }

  }

}
void MainWindow::openDatabase(){
    QString fileName = QFileDialog::getOpenFileName(new QFileDialog, tr("Open File"),
                                                    "",
                                                    tr("Plik danych (*.xml)"));

   // delete ourBase;
  //  ourBase =0;
    ourBase = new DataBase(fileName) ;
    loadBase(ourBase);
}

void MainWindow::saveDatabase(){
    //processBase->
}

void MainWindow::editProduct(){
    productDialog *dialog = new productDialog(ourBase);
    dialog->show();
}

void MainWindow::editSubProducts(){
    subProductDialog *dialog = new subProductDialog(subProductModel);
    dialog->show();
}
void MainWindow::editSuppliers(){
    QStringList subProductList;
    for(int i=0;i<subProductModel->rowCount();i++){
        subProductList.append( subProductModel->data(subProductModel->index(i,0)).toString());
    }
    suppliersDialog *dialog = new suppliersDialog(suppliersModel,subProductList);
    dialog->show();

}
void MainWindow::editTabu(){
    setTabu *dialog = new setTabu();
    connect( dialog,SIGNAL( saveTabu(int,int,int,int,int,int,int,int)),
             this, SLOT(on_saveTabu(int,int,int,int,int,int,int,int)));
    connect(this, SIGNAL(tabuParam(int,int,int,int,int,int,int,int)),
            dialog, SLOT(on_tabu_param(int,int,int,int,int,int,int,int)) );
    emit tabuParam(_iter,  _iterImprov, _improv, _tabuLength,
                   _iterJump,_iterLocalJump, _kara, _nagroda);
    dialog ->show();
}

void MainWindow::setProcessBase(){
    processBase->clearProducts();
    processBase->amount= ourBase->amount;
    processBase->dailyProduction=ourBase->dailyProduction;
    processBase->deadline=ourBase->deadline;
    for(int i=0;i<subProductModel->rowCount();i++){
        Product temp;

        temp.productName = subProductModel->data(subProductModel->index(i,0)).toString();
        temp.unit = subProductModel->data(subProductModel->index(i,1)).toString();
        temp.quantity = subProductModel->data(subProductModel->index(i,2)).toInt();

        for(int j=0;j<suppliersModel->rowCount();j++){
            if( suppliersModel->data(suppliersModel->index(j,1)).toString() == subProductModel->data(subProductModel->index(i,0)).toString() ){
                temp.addSupplier(suppliersModel->data(suppliersModel->index(j,0)).toString(),
                                 suppliersModel->data(suppliersModel->index(j,1)).toInt(),
                                 suppliersModel->data(suppliersModel->index(j,2)).toInt(),
                                 suppliersModel->data(suppliersModel->index(j,3)).toInt()
                                 );
            }
        }
        processBase->addProduct(temp);
    }
    suppliersModel->clear();
    subProductModel->clear();
    loadBase(processBase);
}

void MainWindow::on_START_clicked()
{
  setProcessBase();
  qDebug("start");
  _firstSolution.fill(1,processBase->countProducts());
  algTabu = new workerThread(processBase,  _iter,  _iterImprov, _improv, _tabuLength,
                             _iterJump,_iterLocalJump, _firstSolution, _kara, _nagroda);
  connect(algTabu->algorithm ,SIGNAL(step(int,QVector<double>,QVector<int>)),
          this,SLOT(on_algStep(int , QVector<double> , QVector<int>))  );
  solutionModel->clear();
  solutionModel->setColumnCount(2);
  ui->my_plot->addGraph();
  algTabu ->run();
}
void MainWindow::on_algStep(int number,  QVector<double> values,QVector<int> bestSolution){
    Product temp;
    Supplier tempSup;
    qDebug("on_alg_step");
    iteracje.append(double(number) );
    if(posMinElement != std::min_element(values.begin(), values.end()) - values.begin()){
        posMinElement =  std::min_element(values.begin(), values.end()) - values.begin();
        solutionModel->clear();
        solutionModel->setColumnCount(2);
        for(int i=0;i<subProductModel->rowCount();i++){
            solutionModel->insertRow(i);
            temp = processBase->getProduct(i);
            solutionModel->setData(solutionModel->index(i,0),QVariant(temp.getName()));//subProductModel->data(subProductModel->index(i,0)));
            tempSup = temp.getSupplier(bestSolution[i]);
            solutionModel->setData(solutionModel->index(i,1),QVariant(tempSup.getName()));
        }
        ui->koszt->setText(QString::number(values[posMinElement]));
        ui->czas->setText(QString::number(bestSolution[bestSolution.size()-1]));
        ui->solutionTable->show();
    }

    ui->my_plot->graph(0)->setData(iteracje, values);
    // give the axes some labels:
    ui->my_plot->xAxis->setLabel("Iteracja");
    ui->my_plot->yAxis->setLabel("Wartosc ");
    // set axes ranges, so we see all data:
    ui->my_plot->xAxis->setRange(0, iteracje[iteracje.size()-1]);
    std::vector<double> vecTemp = values.toStdVector();
    double min = *(std::min_element(vecTemp.begin(), vecTemp.end()));

    double max = *(std::max_element(vecTemp.begin(), vecTemp.end()));
    ui->my_plot->yAxis->setRange(min - 15, max + 15 );
    QVector<double> vec_min;
    vec_min.fill(min,iteracje.size());
    ui->my_plot->graph(1)->setData(iteracje, vec_min);
    ui->my_plot->graph(1)->setPen(QPen(Qt::red));
    ui->my_plot->replot();
    ui->my_plot->show();
    this->show();
}
void MainWindow::on_saveTabu(int iter, int iterImprov, int improv, int tabuLength, int iterJump, int iterLocalJump, int kara, int nagroda){
     _iter = iter;
     _iterImprov = iterImprov;
     _improv = improv;
     _tabuLength = tabuLength;
     _iterJump = iterJump;
     _iterLocalJump = iterLocalJump;
     _kara = kara;
     _nagroda =  nagroda;
}
